import 'isomorphic-fetch';
import { API_HOST, Credentials } from 'Constants/config';
import { requestLogout } from 'Actions/userAction';
import { genQuery } from './index';

const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];

const PPHeader = {
  Accept: 'application/json',
  'Content-Type': 'application/json',
};

const GDHeader = {
  Accept: 'application/json',
};

class _Api {
  constructor(opts) {
    this.opts = opts || {};
    if (!methods.includes(opts.method)) {
      this.throwError(`${opts.method}方法不支持`);
    }

    // 默认使用API_HOST
    this.opts.host = opts.host || API_HOST;
    this.opts.url = `${this.opts.host}${this.opts.path ? this.opts.path : ''}`;

    // query传入object就可以
    if (opts.query) {
      const query = genQuery(opts.query);
      this.opts.url = `${this.opts.url}?${query}`;
    }

    // 设置Headers
    if (opts.method === 'GET') {
      this.opts.headers = Object.assign({}, GDHeader, {
        ...opts.header,
      });
    } else {
      this.opts.headers = Object.assign({}, PPHeader, {
        ...opts.header,
      });
    }
    if (opts.noHeader) {
      this.opts.headers = {};
    }
    // 设置同源策略
    this.opts.credentials = Credentials;
  }

  run() {
    let config = {};
    // 如果没有设置 Content-Type 则默认为 application/json
    if (!this.opts.noHeader && (!this.opts.headers['Content-Type'] || this.opts.headers['Content-Type'] === 'application/json')) {
      this.opts.data = JSON.stringify(this.opts.data);
    }

    if (this.opts.method === 'GET') {
      config = {
        credentials: this.opts.credentials,
        method: this.opts.method,
        headers: this.opts.headers,
      };
    } else {
      config = {
        credentials: this.opts.credentials,
        method: this.opts.method,
        headers: this.opts.headers,
        body: this.opts.data,
      };
    }

    return fetch(this.opts.url, config)
      .then(response => (
        this.checkStatus(response, this.opts.success, this.opts.error, this.opts.tips)
      ))
      .catch(err => (
        Promise.reject(err)
      ));
  }

  checkStatus(response, success = () => {
  }, error = () => {
  }) {
    const status = response.status;
    const ctflag = response.headers.get('Content-Type');
    switch (status) {
      case 200: {
        if (ctflag) {
          return (response.json()).then((json) => {
            success(json);
          });
        }
        success();
        break;
      }
      case 403: {
        window.store.dispatch(requestLogout());
        success();
        break;
      }
      default: {
        return (response.json()).then((json) => {
          error(json.message);
        });
      }
    }
    return Promise.resolve();
  }

  throwError(msg) {
    console.log(msg);
  }
}

const Api = _Api;
export default Api;
